package com.sitech.ibnms.util.export;

import com.sitech.ibnms.util.domain.SysDictItem;
import java.io.*;
import java.util.*;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;

/**
 *
 * @author liujhc <liujhc@si-tech.com.cn>
 */
public class ExcelExporter {

    private static final Log log = LogFactory.getLog(ExcelExporter.class);
    /**
     * 内存中只保留100行，超出的将缓冲到磁盘
     */
    private final SXSSFWorkbook workbook = new SXSSFWorkbook(100);
    private int currentSheetIndex = 0;
    private LinkedHashMap<String, String> header;
    private List<String> headerKeys;

    public ExcelExporter(LinkedHashMap<String, String> header) {
        this.header = header;
        headerKeys = Arrays.asList(header.keySet().toArray(new String[]{}));
    }

    /**
     * 创建新的Sheet,并将之作为当前Sheet
     *
     * @return
     */
    public int createSheet() {
        Sheet sheet = workbook.createSheet();
        currentSheetIndex = workbook.getSheetIndex(sheet);
        if (!header.containsValue(null)) {
            addRow(header, 0);
        }
        return currentSheetIndex;
    }

    /**
     * 创建新的Sheet,并将之作为当前Sheet
     *
     * @param sheetName
     * @return
     */
    public int createSheet(String sheetName) {
        Sheet sheet = workbook.createSheet(sheetName);
        currentSheetIndex = workbook.getSheetIndex(sheet);
        if (!header.containsValue(null)) {
            addRow(header, 0);
        }
        return currentSheetIndex;
    }

    /**
     * 切换当前的Sheet
     *
     * @param sheetIndex 要被切换到当前的Sheet序号
     * @return 返回切换后当前位置Sheet的名称
     */
    public String switchSheetToCurrent(int sheetIndex) {
        currentSheetIndex = sheetIndex;
        return workbook.getSheetName(currentSheetIndex);
    }

    /**
     * 向Sheet中添加行
     *
     * @param bean
     * @return 返回最后一行的行号
     */
    public int addRow(Object bean) {
        Sheet sheet = workbook.getSheetAt(currentSheetIndex);
        return addRow(bean, sheet.getLastRowNum() + 1);
    }

    /**
     * 向Sheet中添加行
     *
     * @param bean
     * @param dicts
     * @return 返回最后一行的行号
     */
    public int addRow(Object bean, Map<String, Map<String, SysDictItem>> dicts) {
        Sheet sheet = workbook.getSheetAt(currentSheetIndex);
        return addRow(bean, sheet.getLastRowNum() + 1, dicts);
    }

    /**
     * 向Sheet中的指定位置添加行
     *
     * @param bean
     * @param rownum
     * @return 返回最后一行的行号
     */
    public int addRow(Object bean, int rownum) {
        return addRow(bean, rownum, Collections.EMPTY_MAP);
    }

    /**
     * 向Sheet中的指定位置添加行
     *
     * @param bean
     * @param rownum
     * @param dicts
     * @return 返回最后一行的行号
     */
    public int addRow(Object bean, int rownum, Map<String, Map<String, SysDictItem>> dicts) {
        Sheet sheet = workbook.getSheetAt(currentSheetIndex);
        Row row = sheet.createRow(rownum);
        Map<String, Object> map;
        if (bean instanceof Map) {
            map = (Map) bean;
        } else {
            try {
                map = BeanUtils.describe(bean);
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }
        }
        for (int i = 0; i < headerKeys.size(); i++) {
            String columnName = headerKeys.get(i);
            String value = map.get(columnName) == null ? "" : map.get(columnName).toString();
            //字典翻译
            Map<String, SysDictItem> dictItemsMap = dicts.get(columnName);
            if (dictItemsMap != null && dictItemsMap.containsKey(value)) {
                value = dictItemsMap.get(value).getItemName();
            }
            row.createCell(i).setCellValue(value);
        }
        return sheet.getLastRowNum();
    }

    /**
     * 导出的格式为2007
     *
     * @return
     * @throws IOException
     */
    public InputStream export() throws IOException {
        final PipedOutputStream pos = new PipedOutputStream();
        new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    workbook.write(pos);
                    pos.flush();
                } catch (IOException ex) {
                    log.error(ex);
                } finally {
                    try {
                        pos.close();
                    } catch (IOException ex) {
                        log.error(ex);
                    }
                }
            }
        }).start();
        return new PipedInputStream(pos);
    }

    /**
     * 写入到输出流（office 2007格式）
     *
     * @param stream
     * @throws IOException
     */
    public void write(OutputStream stream) throws IOException {
        workbook.write(stream);
    }

    public static void main(String[] args) throws Exception {
        LinkedHashMap header = new LinkedHashMap();
        header.put("eventId", "告警标识");
        header.put("eventTitle", "告警标题");
        ExcelExporter expoter = new ExcelExporter(header);
        expoter.createSheet("告警列表");
        expoter.addRow(header);
        expoter.addRow(header);
        expoter.createSheet("告警列表2");
        expoter.addRow(header);
        InputStream is = expoter.export();

        FileOutputStream fos = new FileOutputStream(new File("E://export.xlsx"));
        byte[] bytes = new byte[1024];
        int length = 0;
        while ((length = is.read(bytes)) != -1) {
            fos.write(bytes, 0, length);
        }
        fos.close();

        is.close();
    }
}
